package movement;

/**
 * A class for creating a Location
 */
public class Location implements Cloneable {
	/**
	 * Variable registering the X-coordinate of this location
	 */
	private int X;

	/**
	 * Variable registering the Y-coordinate of this location
	 */
	private int Y;

	/**
	 * Variable registering the name of this location
	 */
	private String name;

	/**
	 * Initialize this new location with given coordinates (X and Y) and a name
	 * 
	 * @param 	X
	 *         	The X-coordinate of this location
	 * 
	 * @param 	Y
	 *          The Y-coordinate of this location
	 * 
	 * @param 	name
	 *          The name of this location
	 * 
	 * @post 	The X-coordinate of this Location is set to the given coordinate
	 * 
	 * @post 	The Y-coordinate of this Location is set to the given coordinate
	 * 
	 * @post 	The name of this Location is set to the given name
	 */
	public Location(int X, int Y, String name) {
		setX(X);
		setY(Y);
		setName(name);
	}
	
	/**
	 * Initialize this new location with given coordinates in string format
	 * 
	 * @param c1
	 *        The x coordinate of this location
	 *        c2 
	 *        The y coordinate of this location
	 * 
	 * @post The X-coordinate of this Location is set to the given coordinate
	 * 
	 * @post The Y-coordinate of this Location is set to the given coordinate
	 * 
	 * @throws IllegalArgumentException, if the location string is not valid
	 */
	public Location(String c1, String c2, String name) {
		int x = 0, y = 0;
		c1 = c1.replace("(", "");
		c2 = c2.replace(")", "");
		
		try{
			x = Integer.parseInt(c1);
			y = Integer.parseInt(c2);
		}
		catch (Exception e){
			throw new IllegalArgumentException("Location(string string) has to be valid");
		}
		setX(x);
		setY(y);
		setName(name);
	}

	/**
	 * Method for changing this Location it's coordinates, 
	 * using a given location , and the distance to that point
	 * 
	 * @param 	whereTo
	 * 			The destination location
	 * 
	 * @param 	maxDistance
	 * 			The maximum distance to the whereTo location
	 * 
	 * @post 	The x coordinate of this Location is changed
	 * 
	 * @post 	The y coordinate of this Location is changed
	 * 
	 * @post 	The name of this Location is changed
	 * 
	 */
	public void changeLocation(Location whereTo, double maxDistance){
		double devider = distance(whereTo) / maxDistance;
		setName("heading for " + whereTo.getName());
		setX((int) (Math.ceil((whereTo.getX()-getX())/devider)+getX()));
		setY((int) (Math.ceil((whereTo.getY()-getY())/devider)+getY()));
	}
	
	
	/**
	 * Method for creating a clone of this Location
	 * 
	 * @return Returns a clone of this Location object
	 */
	public Object clone() {    
        Location loc = new Location(this.getX(), this.getY(), this.getName());
        return loc;
    }
    

	/**
	 * Method for comparing the distance from this location to def-location with the distance from the given location s2 to def-location
	 * 
	 * @param 	s2
	 * 			The location 
	 * @param 	def
	 * 			The start location, both (this and s2) locations are compared with this one
	 * 
	 * @return 	Returns 0 when distance this of location to def-location is equal with distance s2-location to def-location 
	 * 			1 or -1 if ain't equal
	 */
	public int compareTo(Location s2, Location def) {
		if (this.distance(def) > s2.distance(def))
			return 1;
		else if (this.distance(def) < s2.distance(def))
			return -1;
		else
			return 0;
	}

	/**
	 * Method for computing the distance between this Location and the given
	 * x and y value
	 * 
	 * @param 	x, y
	 *          The x and y value where we need to compute the distance to
	 * 
	 * @return 	Returns the distance between the two locations
	 */
	public double distance(int x, int y){
		int x1 = getX();
		int y1 = getY();
		int x2 = x;
		int y2 = y;

		int part1 = (Math.abs((x2 - x1))) * (Math.abs((x2 - x1)));
		int part2 = (Math.abs((y2 - y1))) * (Math.abs((y2 - y1)));
		
		return Math.sqrt((part1 + part2));
	}
	

	/**
	 * Method for computing the distance between this Location and the given
	 * Location
	 * 
	 * @param 	location
	 *          The Location where we need to compute the distance to
	 * 
	 * @return 	Returns the distance between the two locations
	 */
	public double distance(Location location) {
		if(location != null){
			return distance(location.getX(),location.getY());
		}
		else{
			return 0;
		}
	}

	/**
	 * Method for checking the current location is equals to the given location
	 * 
	 * @param loc
	 *            The location which needs to be checked for equality
	 * 
	 * @return True if both locations and name are equal, false if not
	 * 
	 */
	public boolean equals(Location loc){
		return (this.getX() == loc.getX()) && (this.getY() == loc.getY());
	}

	/**
	 * Getter for getting this Location it's name
	 * 
	 * @return Returns the current name of this Location
	 */
	public String getName() {
		return name;
	}

	/**
	 * Getter for getting this location it's X-coordinate
	 * 
	 * @return Returns the X-coordinate of this Location
	 */
	public int getX() {
		return X;
	}

	/**
	 * Getter for getting this location it's Y-coordinate
	 * 
	 * @return Returns the Y-coordinate of this Location
	 */
	public int getY() {
		return Y;
	}
	

	/**
	 * Method for setting this Location it's name
	 * 
	 * @param name
	 *            The name that needs to be set
	 * 
	 * @post The name of this Location is changed to the given name
	 */
	public void setName(String name) {
		this.name = name;
	}

	
	/**
	 * Method for setting this Location it's X-coordinate
	 * 
	 * @param 	x
	 *          The x-coordinate that needs to be set to this Location
	 * 
	 * @post 	The x-coordinate of this Location is set to the given x-coordinate
	 */
	private void setX(int x) {
		X = x;
	}
	
	/**
	 * Method for setting this Location it's Y-coordinate
	 * 
	 * @param 	y
	 *          The Y-coordinate that needs to be set to this Location
	 * 
	 * @post 	The Y-coordinate of this Location is changed to the given coordinate
	 */
	private void setY(int y) {
		Y = y;
	}
	
	/**
	 * Method for creating a description of this location
	 * 
	 * @return The description of this Location
	 */
	public String toString() {
		return ("Location: " + getName() + " Coordinates: " + getX() + "-" + getY());
	}
}
